package cn.zhentao.service;

import cn.zhentao.mapper.TutorMessageMapper;
import cn.zhentao.pojo.TutorMessage;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;

/**
 * 语音文件管理服务
 * 负责语音文件的MinIO存储、数据库记录和生命周期管理
 * 
 * @author zhentao
 */
@Service
@Slf4j
public class VoiceFileService {

    @Autowired
    private MinioService minioService;

    @Autowired
    private TutorMessageMapper tutorMessageMapper;

    @Value("${minio.voice.bucket-name:video}")
    private String voiceBucketName;

    @Value("${minio.voice.base-url:http://118.31.228.119:19000/video/}")
    private String voiceFileBaseUrl;

    /**
     * 将本地语音文件上传到MinIO并更新消息记录
     * 
     * @param localFilePath 本地语音文件路径
     * @param messageId 消息ID
     * @return MinIO中的文件URL
     */
    public String uploadVoiceFileToMinio(String localFilePath, Long messageId) {
        try {
            File localFile = new File(localFilePath);
            if (!localFile.exists()) {
                log.error("❌ 本地语音文件不存在: {}", localFilePath);
                return null;
            }

            // 生成MinIO中的文件名（存储在video桶的voice目录下）
            String dateFolder = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            String fileName = "voice/" + dateFolder + "/" + UUID.randomUUID().toString() + ".mp3";

            // 上传文件到MinIO的video桶
            try (FileInputStream inputStream = new FileInputStream(localFile)) {
                minioService.uploadFileToSpecificBucket(inputStream.readAllBytes(), fileName, "audio/mpeg", voiceBucketName);
            }

            // 构建文件URL
            String fileUrl = voiceFileBaseUrl + fileName;

            // 更新消息记录
            if (messageId != null) {
                updateMessageVoiceInfo(messageId, fileUrl, fileName, calculateVoiceDuration(localFile));
            }

            // 删除本地临时文件
            if (localFile.delete()) {
                log.info("✅ 本地临时语音文件已删除: {}", localFilePath);
            } else {
                log.warn("⚠️ 本地临时语音文件删除失败: {}", localFilePath);
            }

            log.info("✅ 语音文件上传到MinIO成功: {}", fileUrl);
            return fileUrl;

        } catch (Exception e) {
            log.error("❌ 语音文件上传到MinIO失败: {}", localFilePath, e);
            return null;
        }
    }

    /**
     * 更新消息的语音信息
     * 
     * @param messageId 消息ID
     * @param voiceFileUrl 语音文件URL
     * @param voiceFileName 语音文件名
     * @param voiceDuration 语音时长
     */
    private void updateMessageVoiceInfo(Long messageId, String voiceFileUrl, String voiceFileName, Integer voiceDuration) {
        try {
            TutorMessage message = tutorMessageMapper.selectById(messageId);
            if (message != null) {
                message.setVoiceFileUrl(voiceFileUrl);
                message.setVoiceFileName(voiceFileName);
                message.setVoiceDuration(voiceDuration);
                message.setUpdatedTime(LocalDateTime.now());
                
                tutorMessageMapper.updateById(message);
                log.info("✅ 消息语音信息更新成功: messageId={}, voiceUrl={}", messageId, voiceFileUrl);
            }
        } catch (Exception e) {
            log.error("❌ 更新消息语音信息失败: messageId={}", messageId, e);
        }
    }

    /**
     * 计算语音文件时长（简单估算）
     * 
     * @param voiceFile 语音文件
     * @return 时长（秒）
     */
    private Integer calculateVoiceDuration(File voiceFile) {
        // 简单估算：MP3文件大小(KB) / 16 ≈ 时长(秒)
        // 这是一个粗略的估算，实际应该使用音频库来获取准确时长
        long fileSizeKB = voiceFile.length() / 1024;
        return (int) Math.max(1, fileSizeKB / 16);
    }

    /**
     * 删除会话相关的所有语音文件（从MinIO中删除）
     *
     * @param sessionId 会话ID
     */
    public void deleteVoiceFilesBySessionId(Long sessionId) {
        if (sessionId == null) {
            log.warn("⚠️ 会话ID为空，跳过语音文件删除");
            return;
        }

        try {
            log.info("🗑️ 开始删除会话 {} 的所有语音文件", sessionId);

            // 查询会话中所有包含语音文件的消息
            QueryWrapper<TutorMessage> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("session_id", sessionId)
                       .isNotNull("voice_file_name")
                       .ne("voice_file_name", "")
                       .eq("is_deleted", 0);

            List<TutorMessage> messagesWithVoice = tutorMessageMapper.selectList(queryWrapper);

            if (messagesWithVoice.isEmpty()) {
                log.info("ℹ️ 会话 {} 没有语音文件需要删除", sessionId);
                return;
            }

            int deletedCount = 0;
            int failedCount = 0;

            for (TutorMessage message : messagesWithVoice) {
                try {
                    // 从MinIO删除语音文件
                    deleteVoiceFileFromMinio(message.getVoiceFileName());
                    deletedCount++;

                    // 清空数据库中的语音文件信息
                    message.setVoiceFileUrl(null);
                    message.setVoiceFileName(null);
                    message.setVoiceDuration(null);
                    message.setUpdatedTime(LocalDateTime.now());
                    tutorMessageMapper.updateById(message);

                } catch (Exception e) {
                    failedCount++;
                    log.error("❌ 删除消息 {} 的语音文件失败: {}", message.getId(), message.getVoiceFileName(), e);
                }
            }

            log.info("✅ 会话 {} 语音文件删除完成 - 成功: {}, 失败: {}, 总计: {}",
                    sessionId, deletedCount, failedCount, messagesWithVoice.size());

        } catch (Exception e) {
            log.error("❌ 删除会话语音文件失败: sessionId={}", sessionId, e);
        }
    }

    /**
     * 从MinIO删除单个语音文件
     *
     * @param voiceFileName MinIO中的语音文件名
     * @throws RuntimeException 当删除失败时抛出运行时异常
     */
    private void deleteVoiceFileFromMinio(String voiceFileName) {
        if (voiceFileName == null || voiceFileName.trim().isEmpty()) {
            return;
        }

        try {
            // 从video桶删除文件
            minioService.deleteFileFromSpecificBucket(voiceFileName, voiceBucketName);
            log.debug("✅ MinIO语音文件删除成功: {}", voiceFileName);
        } catch (Exception e) {
            log.error("❌ MinIO语音文件删除失败: {}", voiceFileName, e);
            throw new RuntimeException("删除MinIO语音文件失败: " + voiceFileName, e);
        }
    }

    /**
     * 删除单个语音文件（公共方法）
     *
     * @param voiceFileName MinIO中的语音文件名
     */
    public void deleteVoiceFile(String voiceFileName) {
        if (voiceFileName == null || voiceFileName.trim().isEmpty()) {
            return;
        }

        try {
            deleteVoiceFileFromMinio(voiceFileName);
            log.info("✅ 语音文件删除成功: {}", voiceFileName);
        } catch (Exception e) {
            log.error("❌ 语音文件删除失败: {}", voiceFileName, e);
        }
    }



    /**
     * 检查语音文件是否存在
     * 
     * @param voiceFileName MinIO中的语音文件名
     * @return 是否存在
     */
    public boolean voiceFileExists(String voiceFileName) {
        if (voiceFileName == null || voiceFileName.trim().isEmpty()) {
            return false;
        }

        try {
            return minioService.fileExistsInSpecificBucket(voiceFileName, voiceBucketName);
        } catch (Exception e) {
            log.error("❌ 检查语音文件存在性失败: {}", voiceFileName, e);
            return false;
        }
    }

    /**
     * 获取语音文件的访问URL
     * 
     * @param voiceFileName MinIO中的语音文件名
     * @return 访问URL
     */
    public String getVoiceFileUrl(String voiceFileName) {
        if (voiceFileName == null || voiceFileName.trim().isEmpty()) {
            return null;
        }

        return voiceFileBaseUrl + voiceFileName;
    }


}
